//
//  ZMBleManager.swift
//  vhSixMinProject
//
//  Created by moon_zm on 2025/3/18.
//

import Foundation
import CoreBluetooth
import ZMSaaSFoundation


//设备连接状态
public enum DeviceConnectType {
    case normal //默认，初始化状态, 串口丢失状态
    case connecting //连接中
    case connected //连接成功
    case unconnected //未连接，连接失败
}

public class ZMBleManager:NSObject {
    public static let shared = ZMBleManager()
    //搜索到的CPET设备列表回调
    public var deviceListHandler:((_ devices: [CBPeripheral])->Void)?
    public var deviceConnectHandler:((Bool, String)->Void)?
    public var deviceRSSI:((Int)->())?
    //电池电量,默认100%
    public var batteryValue:Int = 100
    
    public var connectType:DeviceConnectType = .normal {
        didSet {
            if connectType == oldValue {return}
            if connectType == .connecting {
                return
            }
            
            if connectType != .connected {
                stopBatteryTimer()
                deviceConnectHandler?(false, currentDeviceName)
                return
            }
            deviceConnectHandler?(true, currentDeviceName)
            //设备连接成功开启电量查询
            startBatteryTimer()
        }
    }
    public var currentDeviceName:String = ""
    
    //间隔60s获取电池电量
    private var batteryTimer:Timer?
    private let batteryTimeInterval:TimeInterval = 0.5//时间间隔
    
    //当前连接的外设
    private var currentPeripheral: CBPeripheral?
    private var service: CBService?
    private let serviceid = "FFF0"
    private let characteristicid_r = "FFF1"
    private let characteristicid_w = "FFF2"
    private var characteristic_r:CBCharacteristic?
    private var characteristic_w:CBCharacteristic?
    
    //是否断开连接
    private var handleDisconnect: Bool?
   
    //搜索到的CPET设备列表
    private var deviceList:[CBPeripheral] = []

    private lazy var btManager:CBCentralManager = {
        let manager = CBCentralManager()
        return manager
    }()
    
    func startBatteryTimer() {
        stopBatteryTimer()
//        sendOrderWithDevice(.acpt_battery_status_start)
        batteryTimer = Timer.ex_scheduledTimer(with: batteryTimeInterval, block: {[weak self] timer in
            guard let self = self else { return }
            currentPeripheral?.readRSSI()
//            self.sendOrderWithDevice(.acpt_battery_status_start)
        }, repeats: true)
    }
    
    func stopBatteryTimer() {
        batteryTimer?.ex_resetTimer()
        batteryTimer = nil
    }
}

//MARK: - 蓝牙相关 -
extension ZMBleManager {
    //清理搜索的设备
    public func cleanDeviceList() {
        deviceList.removeAll()
        deviceListHandler?([])
    }
    //搜索CPET
    public func scanDevice(){
        handleDisconnect = false
        cleanDeviceList()
        stopScan()
        startScan()
    }
    
    //主动连接设备
    public func connectDevice(deviceName:String) {
        currentDeviceName = deviceName
        //连接过设备重连时
        if let peripheral = currentPeripheral, peripheral.name == deviceName {
            connect(device: peripheral)
            return
        }
        //外部有记录名字,并且搜索到时优先连接
        if let peripheral = checkHavDevice(deviceName: deviceName) {
            connect(device: peripheral)
        } else {
            //外部有保留名字，连接前未搜索到名字时，重新搜索
            startScan()
        }
    }
    
    private func checkHavDevice(deviceName:String) -> CBPeripheral? {
        let checkDevices = deviceList.filter({$0.name == deviceName})
        if checkDevices.count > 0 {
            return checkDevices.first
        }
        return nil
    }
    
    //主动断开连接心肺
    public func disconnected() {
        handleDisconnect = true
        cleanDeviceList()
        if connectType == .connected, let peripheral = currentPeripheral {
            btManager.cancelPeripheralConnection(peripheral)
        }
        connectType = .normal
        btManager.delegate = nil
        currentPeripheral = nil
        currentDeviceName = ""
    }
    
    private func startScan() {
        btManager.delegate = self
        btManager.scanForPeripherals(withServices: nil, options: nil)
    }
    
    public func stopScan() {
        btManager.stopScan()
    }
    
    private func connect(device:CBPeripheral) {
        connectType = .connecting
        btManager.connect(device, options: nil)
        handleDisconnect = false
    }

    //搜索服务
    private func discoverServices(device:CBPeripheral) {
        device.delegate = self
        device.discoverServices(nil)
    }
}



//MARK: - CBCentralManagerDelegate
extension ZMBleManager: CBCentralManagerDelegate {
    public func centralManagerDidUpdateState(_ central: CBCentralManager) {
        switch (central.state) {
        case .poweredOn:
            btManager.scanForPeripherals(withServices: nil, options: nil)
            print("蓝牙已打开, 正在扫描外设!");
            break;
        case .poweredOff:
//            btManager.scanForPeripherals(withServices: nil, options: nil)
            print("蓝牙关闭，请先打开蓝牙");
        default:
            break;
        }
    }
   
    public func centralManager(_ central: CBCentralManager, didDiscover peripheral: CBPeripheral, advertisementData: [String : Any], rssi RSSI: NSNumber) {
        if peripheral.name?.lowercased().contains("holy") == true {
            NSLog("scan_peripheral:%@", peripheral.name ?? "")
            addDeviceList(peripheral: peripheral)
            //外部有记录名字时优先连接
            if currentDeviceName == peripheral.name {
                connect(device: peripheral)
                return
            }
            //当前连接蓝牙自动连接
            if let perip = currentPeripheral, perip.name == peripheral.name {
                connect(device: peripheral)
            }
            
        }
    }
    
    public func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
        currentDeviceName = peripheral.name ?? ""
        currentPeripheral = peripheral
        connectType = .connected
        discoverServices(device: peripheral)
        stopScan()
    }
    
    public func centralManager(_ central: CBCentralManager, didDisconnectPeripheral peripheral: CBPeripheral, error: Error?) {
        NSLog("发出 异常关闭 DisconnectPeripheral 事件给 Handler");
        connectType = .unconnected
        // 如果 handleDisconnect == false 说明是非人为断开连接，需要进行重连操作
        if handleDisconnect == false {
            startScan()
            connect(device: peripheral)
        }
        
    }
    
    
    private func addDeviceList(peripheral:CBPeripheral) {
        let havDevices = deviceList.filter({$0.name == peripheral.name})
        if havDevices.count > 0{
            return
        }
        deviceList.append(peripheral)
        self.deviceListHandler?(deviceList)
    }
}

//MARK: - CBPeripheralDelegate
extension ZMBleManager : CBPeripheralDelegate {
    
    public func peripheral(_  peripheral: CBPeripheral, didDiscoverServices error: Error?) {
        for service in peripheral.services! {
            if service.uuid.uuidString == serviceid{
                self.service = service
                peripheral.discoverCharacteristics(nil, for: service)
            }
        }
            
    }
    
    public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?){
        for characteristic in service.characteristics! {
            if characteristic.uuid.uuidString == characteristicid_r {
                characteristic_r = characteristic
                peripheral.setNotifyValue(true, for: characteristic)
            } else if characteristic.uuid.uuidString == characteristicid_w {
                characteristic_w = characteristic
            }
        }
    }
    
    public func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?){
    }
    
    public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)-> (){
        
        if characteristic.uuid.uuidString == characteristicid_r {
            guard let data = characteristic.value else { return }
//            let str = data.ex_toHex(withSpace: false)
//            debugPrint("CPET_data:\(str)")
//            self.dataAnalyse.decodeCommand(data.ex_bytes)
            return
        }
    }
    public func peripheral(_ peripheral: CBPeripheral, didReadRSSI RSSI: NSNumber, error: (any Error)?) {
        self.deviceRSSI?(RSSI.intValue)
    }
}

public extension Data {
    /// 按照 ASCII 转换成字符串
        func ex_toAscii() -> String {
            return subdata2ascii(start: 0, end: self.count)
        }
        
        /// 转换成16进制字符串
        /// - Parameter withSpace: 可选参数，默认true，输出的字符串是否每两个字节之间放一个空格
        public func ex_toHex(withSpace: Bool = true) -> String {
            return subdata2hex(start: 0, end: self.count, withSpace: withSpace)
        }
    
    /// 将指定范围的数据转换成ASCII字符串
        /// - Parameter start: 起始索引（包含）
        /// - Parameter end: 结束索引（不包含）
        func subdata2ascii(start: Int, end: Int) -> String {
            if let str = String(data: self[start..<end], encoding: .ascii) {
                return str
            }
            return ""
        }
        
        /// 将指定范围的数据转换成16进制字符串
        /// - Parameter start: 起始索引（包含）
        /// - Parameter end: 结束索引（不包含）
        /// - Parameter withSpace: 可选参数，默认true，输出的字符串是否每两个字节之间放一个空格
        func subdata2hex(start: Int, end: Int, withSpace: Bool = true) -> String {
            let arr = Array<UInt8>(self[start..<end])
            let hex = arr.map({ byte -> String in
                return String(format: "%02X", byte)
            }).joined(separator: withSpace ? " " : "")
            return hex
        }
   
}
